C言語メモ
| ■ | typedef とdefineの違い | |||||||||||||||||||||||||||||||||||
| typedefは新しいデータ型の名前(別名)を作成するものです。 (例) typedef int myINT は、 myINTと云う同義語をつくり その意味は intです。 すなわち myINT a; は int a; と同等に扱われます。 一方、 #define myINT int も myINT a; は int a; と同等に扱われます。 しかし myINT a,b; はエラーとなる。 コンパイラは int a; は理解するが bに関しては解釈不能となる。 ★★ #defineはプリプロセッサにより解釈され、typedefはコンパイラが解釈する。 |
||||||||||||||||||||||||||||||||||||
| ■ | typedef による定義 | |||||||||||||||||||||||||||||||||||
| ■ 予約語 typedefの意味 typedef int myINT; と書くと myINTは intの別名(エイリアス)となり myINT i = 7, j = 8, k = 9; i, j, kは それぞれ7,8,9の整数である。 |
||||||||||||||||||||||||||||||||||||
したがって、![]() は、正確に表現すると、『型名 struct RECA{ int x; int y}の構造体の別名型が RECAであることを定義』している。 上記の定義に於いては構造体のタグ名RECAと別名RECAが同じであるが、定義に於いてタグ名と別名が異なっても またタグ名が無くてもよい。 プログラムの実行結果に差異はない。 タグ名は無効であり、使えない。 以下、参照 |
||||||||||||||||||||||||||||||||||||
#include <stdio.h>
//構造体タグ名RECAは、別名の型名RECAと同じ場合
typedef struct RECA //タグ名
{
int x;
int y;
} RECA; //型名
//構造体タグ名なしの場合
typedef struct
{
int x;
int y;
} RECB; //型名
//構造体タグ名と別名の型名は異なる場合
typedef struct XYZ //タグ名 //→ タグ名 XYZはプログラムの中では無効であり、使えない。
{
int x;
int y;
} RECC; //型名
int main()
{
RECA reca; //RECA reca;が無いとreca.x = 1;reca.y = 2;がコンパラエラーとなる
reca.x = 1;
reca.y = 2;
RECB recb;
recb.x = 3;
recb.y = 4;
RECC recc;
recc.x = 5;
recc.y = 6;
// XYX xyz; //XYZ xyz;はコンパイラエラーとなる
printf("reca.x=%d, reca.y=%d\n",reca.x, reca.y);
printf("recb.x=%d, recb.y=%d\n",recb.x,recb.y);
printf("recc.x=%d, recc.y=%d\n",recc.x,recc.y);
return 0;
}
|
||||||||||||||||||||||||||||||||||||
| <実行結果> | ||||||||||||||||||||||||||||||||||||
| reca.x=1, reca.y=2 recb.x=3, recb.y=4 recc.x=5, recc.y=6 |
||||||||||||||||||||||||||||||||||||
| (参考使用例:Harmony gfx_driver.h) → URL | ||||||||||||||||||||||||||||||||||||
| ■ 構造体の定義に typedef を使うメリット | ||||||||||||||||||||||||||||||||||||
| 1. 構造体を宣言する時(オブジェクトを生成する時) struct を書く手間が省ける。 2. ソースコードの可読性が向上する。 3. オブジェクト指向的なソースコードをつくることができる |
||||||||||||||||||||||||||||||||||||
| <typedefを使用した場合> | ||||||||||||||||||||||||||||||||||||
//Harmony app.h より typedef struct //構造体を定義
{
/* The application's current state */
APP_STATES state;
/* TODO: Define any additional data used by the application. */
} APP_DATA;
APP_DATA appData; //構造体を宣言、オブジェクトを生成
| ||||||||||||||||||||||||||||||||||||
| <typedefを使用しない場合> | ||||||||||||||||||||||||||||||||||||
struct //構造体を定義
{
/* The application's current state */
APP_STATES state;
/* TODO: Define any additional data used by the application. */
} APP_DATA;
struct APP_DATA appData; //構造体を宣言、オブジェクトを生成
|
||||||||||||||||||||||||||||||||||||
| ■ C++、Javaのクラスとの記述比較 | ||||||||||||||||||||||||||||||||||||
| Cでtypedef を使った記述をすることにより、C++やJavaのようなオブジェクト指向的なコードを書くことができるようになる。 | ||||||||||||||||||||||||||||||||||||
| 1. Cのtypedefを使った記述 | ||||||||||||||||||||||||||||||||||||
#include<stdio.h>
typedef struct
{
int x;
int y;
}REC;
int main()
{
REC rec;
rec.x = 1;
rec.y = 2;
printf("rec.x=%d\n", rec.x);
printf("rec.y=%d", rec.y);
}
|
||||||||||||||||||||||||||||||||||||
| <実行結果> | ||||||||||||||||||||||||||||||||||||
| rec.x=1 rec.y=2 |
||||||||||||||||||||||||||||||||||||
| 2. C++のクラスを使った記述 | ||||||||||||||||||||||||||||||||||||
#include<iostream>
using namespace std;
class REC{
public:
int x;
int y;
};
int main()
{
REC rec;
rec.x = 1;
rec.y = 2;
cout<<"rec.x = "<<rec.x<<endl;
cout<<"rec.y = "<<rec.y<<endl;
return 0;
}
|
||||||||||||||||||||||||||||||||||||
| <実行結果> | ||||||||||||||||||||||||||||||||||||
| rec.x = 1 rec.y = 2 |
||||||||||||||||||||||||||||||||||||
| 3. Javaのクラスを使った記述 | ||||||||||||||||||||||||||||||||||||
class REC{
int x;
int y;
}
public class Java_Variable_xy {
public static void main(String[] args) {
REC rec = new REC();
rec.x = 1;
rec.y = 2;
System.out.println("rec.x = " + rec.x );
System.out.println("rec.y = " + rec.y );
}
}
|
||||||||||||||||||||||||||||||||||||
| <実行結果> | ||||||||||||||||||||||||||||||||||||
| rec.x = 1 rec.y = 2 |
||||||||||||||||||||||||||||||||||||
| ■ typedef enum | ||||||||||||||||||||||||||||||||||||
C言語でオブジェクト指向のプログラミングをする場合、 構造体と同様に、『名前付き整数定数に typedef enum を用いて列挙型の別名を定義する』 ことが行われる。![]() 『列挙型 { APP_STATE_INIT=0,APP_STATE_DISK_SCANNING,APP_STATE_OPEN_FILE,APP_STATE_SEND_DATA,}の別名型が APP_STATES であることを定義』している。 以下、参照 |
||||||||||||||||||||||||||||||||||||
#define _CORE_TIMER_VECTOR 0
#define _EXTERNAL_0_VECTOR 3
#define _UART6_RX_VECTOR 189
#define _ADC7_WARM_VECTOR 213
#include <stdio.h>
typedef enum
{
APP_STATE_INIT=0,
APP_STATE_DISK_SCANNING,
APP_STATE_OPEN_FILE,
APP_STATE_SEND_DATA,
} APP_STATES; //アプリケーションの状態を示す列挙型APP_STATESを定義
typedef enum
{
COLOR_Red = 0xf800,
COLOR_Blue = 0x001f,
COLOR_NavyBlue = 0x0019,
COLOR_ForestGreen = 0x1c43,
}SYS_COLOR; //色を示す列挙型SYS_COLORを定義
typedef enum
{
INT_SOURCE_CORE_TIMER = _CORE_TIMER_VECTOR,
INT_SOURCE_EXTERNAL_0 = _EXTERNAL_0_VECTOR,
INT_SOURCE_UART6_RX = _UART6_RX_VECTOR,
INT_SOURCE_ADC7_WARM = _ADC7_WARM_VECTOR,
} INT_SOURCE; //割込みベクタ番号の列挙型を定義
typedef struct
{
APP_STATES state; //アプリケーションの状態の列挙型メンバー変数、
SYS_COLOR color; //色の列挙型メンバー変数
INT_SOURCE source; ////割込みベクタ番号の列挙型メンバー変数
} APP_DATA; //アプリケーションのデータを格納する構造体を定義
int main()
{
APP_DATA appData; //構造体の変数宣言、オブジェクト生成
appData.state = APP_STATE_OPEN_FILE; //メンバー変数、オブジェクトを初期化
appData.color = COLOR_NavyBlue;
appData.source = _UART6_RX_VECTOR;
printf("appData.state = %d, APP_STATE = APP_STATE_OPEN_FILE\n",appData.state);
printf("appData.color = 0x%04x, SYS_COLOR = COLOR_NavyBlue\n",appData.color);
printf("appData.source = %d, INT_SOURCE = _UART6_RX_VECTOR\n",appData.source);
return 0;
}
|
||||||||||||||||||||||||||||||||||||
| <実行結果> | ||||||||||||||||||||||||||||||||||||
| appData.state = 2, APP_STATE = APP_STATE_OPEN_FILE appData.color = 0x0019, SYS_COLOR = COLOR_NavyBlue appData.source = 189, INT_SOURCE = _UART6_RX_VECTOR |
||||||||||||||||||||||||||||||||||||
| ■ | uintptr_t | |||||||||||||||||||||||||||||||||||
| ・ ポインタと同じサイズの符号なし整数。 ・ Cで、ポインター保持に充分な大きさの符号なしの整数型。C99(ISO/IEC 9899:1999)で追加された。(使用例 → URL) |
||||||||||||||||||||||||||||||||||||
| ■ | 関数ポインタ | |||||||||||||||||||||||||||||||||||
関数ポインタで関数を呼び出す方法
|
||||||||||||||||||||||||||||||||||||
| (参考使用例: Harmony sys_time_definitions.h) → URL | ||||||||||||||||||||||||||||||||||||
| ■ 関数ポインタメモ | ||||||||||||||||||||||||||||||||||||
| ■ | 関数へのポインタをメンバーにもつ構造体 | |||||||||||||||||||||||||||||||||||
| ・ C言語では構造体の中に関数をメンバーとしてもつことはできないが、関数ポインタを利用すると 関数へのポインタをメンバー変数をもつ構造体をつくることができる。これを使って、同じ呼び出しで異なる関数の呼び出しができる。 この手法はHarmonyの中でよく用いられている。 | ||||||||||||||||||||||||||||||||||||
//10 interface_struct1.c
//同じ呼び出しで異なる関数を呼び出す
#include <stdio.h>
typedef int (*ADD)(int x,int y); //ADDはintを戻り値とする関数名(ポインタ)であると宣言
typedef int (*MUL)(int x,int y); //MULはintを戻り値とする関数名(ポインタ)であると宣言
typedef struct
{
ADD add; //関数名ADDの変数addを宣言
MUL mul; //関数名MULの変数mulを宣言
}FUNC_INTERFACE; //関数へのポインタをメンバーとする構造体を宣言
typedef struct
{
int x; //整数の変数xを宣言
int y; //整数の変数yを宣言
FUNC_INTERFACE func_interface; //関数へのポインタをメンバーとする構造体への変数を宣言
}CALC; //関数へのポインタをメンバー変数にもつ構造体を宣言
int add1(int x, int y)
{
int ans;
ans = x + y + 1;
return ans;
}
int add2(int x, int y)
{
int ans;
ans = x + y + 2;
return ans;
}
int multiply1(int x, int y)
{
int ans;
ans = x * y;
return ans;
}
int multiply2(int x, int y)
{
int ans;
ans = x * y * 2;
return ans;
}
int main()
{
int value;
CALC calc;
FUNC_INTERFACE func_interface = //構造体初期化
{
.add = (ADD)add1, //関数の実体を引き当て
.mul = (MUL)multiply1, //関数の実体を引き当て
};
value = (*func_interface.add)(1,2); //加算演算実行
printf("value = %d\n", value);
value = (*func_interface.mul)(1,2); //乗算演算実行
printf("value = %d\n", value);
calc.x = 3; //CALC構造体のxを初期化
calc.y = 4; //CALC構造体のyを初期化
value = (*func_interface.add)(calc.x,calc.y);
printf("value = %d\n", value);
value = (*func_interface.mul)(calc.x,calc.y);
printf("value = %d\n", value);
//関数変更 //同じ呼び出しで異なる関数を呼び出す
func_interface.add = (ADD)add2;
func_interface.mul = (MUL)multiply2;
value = (*func_interface.add)(1,2);
printf("\nvalue = %d\n", value);
value = (*func_interface.mul)(1,2);
printf("value = %d\n", value);
calc.x = 3;
calc.y = 4;
value = (*func_interface.add)(calc.x,calc.y);
printf("value = %d\n", value);
value = (*func_interface.mul)(calc.x,calc.y);
printf("value = %d\n", value);
}
|
||||||||||||||||||||||||||||||||||||
| <実行結果> | ||||||||||||||||||||||||||||||||||||
| value = 4 value = 2 value = 8 value = 12 value = 5 value = 4 value = 9 value = 24 |
||||||||||||||||||||||||||||||||||||